package com.xyz.update.update;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.os.Environment;
import android.provider.Settings;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.app.NotificationManagerCompat;

import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.PermissionUtils;
import com.xyz.update.R;
import com.xyz.update.UpdateUtils;

/**
 * 应用更新服务
 * 只需要调用init、onResume 即可
 */
public class UpdateService {

    private Context context;
    private boolean isDowning = false;
    private String base_url;
    private String appProjectCode;
    private String token;
    private String deviceId;
    private String downloadUrl;
    private int logo;
    private int dlgTopResId;
    private int btnColor;
    private boolean isClickDownload = false;
    private boolean isTips = false;
    private String moduleId;
    private OnShowUpdateDialog showUpdateDialog;

    private UpdateService() {

    }

    private static final class InstanceHolder {
        @SuppressLint("StaticFieldLeak")
        private volatile static UpdateService instance = new UpdateService();
    }

    public static UpdateService getInstance() {
        return InstanceHolder.instance;
    }

    /**
     * 初始化应用更新
     *
     * @param base_url 域名
     * @param resId    logo
     */
    public void init(Context context, String base_url, String moduleId, int resId) {
        init(context, base_url, moduleId, resId, false);
    }

    public void init(Context context, String base_url, String moduleId, int resId, boolean isTips) {
        initAndShowDlg(context, base_url, moduleId, resId, isTips, null);
    }

    public void initAndShowDlg(Context context, String base_url, String moduleId, int resId, boolean isTips, OnShowUpdateDialog showUpdateDialog) {
        try {
            this.context = context;
            this.base_url = base_url;
            this.moduleId = moduleId;
            this.logo = resId;
            this.isTips = isTips;
            this.showUpdateDialog = showUpdateDialog;
            checkUpdate();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 第二版，传请求链接，post请求，可以自定义背景图片，按钮颜色
     *
     * @param url         请求链接
     * @param dlgTopResId 背景图片
     * @param logoResId   logo
     * @param btnColor    按钮颜色
     */
    public void initV2(Context context, String url, int dlgTopResId, int logoResId, int btnColor) {
        initV2(context, url, dlgTopResId, logoResId, false, btnColor);
    }

    public void initV2(Context context, String url, int dlgTopResId, int logoResId, boolean isTips, int btnColor) {
        initAndShowDlgV2(context, url, dlgTopResId, logoResId, isTips, btnColor, null);
    }

    public void initAndShowDlgV2(Context context, String url, int dlgTopResId, int logoResId, boolean isTips, int btnColor, OnShowUpdateDialog showUpdateDialog) {
        try {
            this.context = context;
            this.base_url = url;
            this.dlgTopResId = dlgTopResId;
            this.logo = logoResId;
            this.isTips = isTips;
            this.btnColor = btnColor;
            this.showUpdateDialog = showUpdateDialog;
            checkUpdateV2();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 第三版，传请求链接，post请求，可以自定义背景图片，按钮颜色 （钱包）
     *
     * @param url            请求链接
     * @param appProjectCode app项目code,移动端传入
     * @param dlgTopResId    背景图片
     * @param logoResId      logo
     * @param btnColor       按钮颜色
     */
    public void initWallet(Context context, String url, String appProjectCode, String token, String deviceId, int dlgTopResId, int logoResId, int btnColor) {
        initWallet(context, url, appProjectCode, token, deviceId, dlgTopResId, logoResId, false, btnColor);
    }

    public void initWallet(Context context, String url, String appProjectCode, String token, String deviceId, int dlgTopResId, int logoResId, boolean isTips, int btnColor) {
        initAndShowWallet(context, url, appProjectCode, token, deviceId, dlgTopResId, logoResId, isTips, btnColor, null);
    }

    public void initAndShowWallet(Context context, String url, String appProjectCode, String token, String deviceId, int dlgTopResId, int logoResId, boolean isTips, int btnColor, OnShowUpdateDialog showUpdateDialog) {
        try {
            this.context = context;
            this.base_url = url;
            this.appProjectCode = appProjectCode;
            this.token = token;
            this.deviceId = deviceId;
            this.dlgTopResId = dlgTopResId;
            this.logo = logoResId;
            this.isTips = isTips;
            this.btnColor = btnColor;
            this.showUpdateDialog = showUpdateDialog;
            checkUpdateV3();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    public void onResume() {
        // 检查通知权限是否已经授予
        boolean granted = NotificationManagerCompat.from(context).areNotificationsEnabled();
        if (granted && isClickDownload) {
            start();
        }
        isClickDownload = false;
    }

    /**
     * 检查最新的版本号
     *
     * @param onBackCodeListener
     */
    public void checkUpdateCode(OnBackCodeListener onBackCodeListener) {
        //检查更新
        String versionNum = AppUtils.getAppVersionName();
        UpdateUtils.getInstance().checkIsUpdate(base_url, versionNum, moduleId, versionInfo -> {
            if (versionInfo != null && onBackCodeListener != null) {
                onBackCodeListener.onBackCode(
                        versionInfo.getAppVersion(), versionInfo.getDescribe(), versionInfo.isUpdate()
                );
            }
            return null;
        });
    }

    public void checkUpdateCodeV2(OnBackCodeListener onBackCodeListener) {
        //检查更新
        String versionNum = AppUtils.getAppVersionName();
        UpdateUtils.getInstance().checkIsUpdateV2(base_url, versionNum, versionInfo -> {
            if (versionInfo != null && onBackCodeListener != null) {
                onBackCodeListener.onBackCode(
                        versionInfo.getAppVersion(), versionInfo.getDescribe(), versionInfo.isUpdate()
                );
            }
            return null;
        });
    }

    public void checkUpdateCodeWallet(OnBackCodeListener onBackCodeListener) {
        //检查更新
        String versionNum = AppUtils.getAppVersionName();
        UpdateUtils.getInstance().checkIsUpdateV3(base_url, appProjectCode, token, deviceId, versionNum, versionInfo -> {
            if (versionInfo != null && onBackCodeListener != null) {
                onBackCodeListener.onBackCode(
                        versionInfo.getAppVersion(), versionInfo.getDescribe(), versionInfo.isUpdate()
                );
            }
            return null;
        });
    }

    /**
     * 检查更新
     */
    private void checkUpdate() {
        //检查更新
        String versionNum = AppUtils.getAppVersionName();
        UpdateUtils.getInstance().checkIsUpdate(base_url, versionNum, moduleId, versionInfo -> {
            if (versionInfo != null) {
                if (versionInfo.isUpdate()) {
                    new XyUpdateDialog(context, versionInfo, needUpdate -> {
                        if (needUpdate) {
                            requestDownloadPath(versionInfo.getVersionNum());
                        }
                    }).show();
                    if (showUpdateDialog != null) {
                        showUpdateDialog.show(true);
                    }
                } else {
                    if (isTips) XyToastUtils.showShort(context.getString(R.string.update_is_new));
                    if (showUpdateDialog != null) {
                        showUpdateDialog.show(false);
                    }
                }
            } else {
                if (showUpdateDialog != null) {
                    showUpdateDialog.show(false);
                }
            }
            return null;
        });
    }

    private void checkUpdateV2() {
        //检查更新
        String versionNum = AppUtils.getAppVersionName();
        UpdateUtils.getInstance().checkIsUpdateV2(base_url, versionNum, versionInfo -> {
            if (versionInfo != null) {
                if (versionInfo.isUpdate()) {
                    new XyUpdateDialog(context, versionInfo, dlgTopResId, btnColor, needUpdate -> {
                        if (needUpdate) {
                            downloadApk(versionInfo.getFileUrl());
                        }
                    }).show();
                    if (showUpdateDialog != null) {
                        showUpdateDialog.show(true);
                    }
                } else {
                    if (isTips) XyToastUtils.showShort(context.getString(R.string.update_is_new));
                    if (showUpdateDialog != null) {
                        showUpdateDialog.show(false);
                    }
                }
            } else {
                if (showUpdateDialog != null) {
                    showUpdateDialog.show(false);
                }
            }
            return null;
        });
    }

    private void checkUpdateV3() {
        //检查更新
        String versionNum = AppUtils.getAppVersionName();
        UpdateUtils.getInstance().checkIsUpdateV3(base_url, appProjectCode, token, deviceId, versionNum, versionInfo -> {
            if (versionInfo != null) {
                if (versionInfo.isUpdate()) {
                    new XyUpdateDialog(context, versionInfo, dlgTopResId, btnColor, needUpdate -> {
                        if (needUpdate) {
                            downloadApk(versionInfo.getFileUrl());
                        }
                    }).show();
                    if (showUpdateDialog != null) {
                        showUpdateDialog.show(true);
                    }
                } else {
                    if (isTips) XyToastUtils.showShort(context.getString(R.string.update_is_new));
                    if (showUpdateDialog != null) {
                        showUpdateDialog.show(false);
                    }
                }
            } else {
                if (showUpdateDialog != null) {
                    showUpdateDialog.show(false);
                }
            }
            return null;
        });
    }

    /**
     * 请求下载地址
     *
     * @param versionNum
     */
    private void requestDownloadPath(String versionNum) {
        UpdateUtils.getInstance().getDownloadUrl(base_url, versionNum, moduleId, downloadUrl -> {
            downloadApk(downloadUrl);
            return null;
        });
    }

    //下载apk
    private void downloadApk(String downloadUrl) {
        this.downloadUrl = downloadUrl;
        if (isDowning) {
            Log.e("downloadApk", "isDowning...");
            return;
        }
        if (context == null) {
            Log.e("downloadApk", "context is null");
            return;
        }
        if (downloadUrl == null) {
            Log.e("downloadApk", "downloadUrl is null");
            return;
        }
        isClickDownload = false;
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
            try {
                if (PermissionUtils.isGranted(PermissionConfig.INSTANCE.getSdcard().toArray(new String[0]))) {
                    toNotificationManager();
                } else {
                    queryDown();
                }
            } catch (Exception e) {
                e.printStackTrace();
                queryDown();
            }
        } else {
            queryDown();
        }
    }

    //只下载apk安装
    public void downloadApk(Context context, String downloadUrl, int logo) {
        this.context = context;
        this.logo = logo;
        downloadApk(downloadUrl);
    }

    private void queryDown() {
        try {
            if (PermissionUtils.isGranted(PermissionConfig.INSTANCE.getSdcard().toArray(new String[0]))) {
                toNotificationManager();
            } else {
                PermissionUtils.permission(PermissionConfig.INSTANCE.getSdcard().toArray(new String[0]))
                        .callback((isAllGranted, granted, deniedForever, denied) -> {
                            if (isAllGranted) {
                                toNotificationManager();
                            } else if (context != null && deniedForever != null && deniedForever.size() > 0) {
                                new AlertDialog.Builder(context)
                                        .setMessage(context.getString(R.string.update_go_sdcrad))
                                        .setNegativeButton(context.getString(R.string.update_cancel), (dialog, which) -> {
                                            dialog.dismiss();
                                        })
                                        .setPositiveButton(context.getString(R.string.update_go), (dialog, which) -> {
                                            PermissionUtils.launchAppDetailsSettings();
                                            dialog.dismiss();
                                        })
                                        .create().show();
                            } else if (context != null && denied != null && denied.size() > 0) {
                                new AlertDialog.Builder(context)
                                        .setMessage(context.getString(R.string.update_sdcrad))
                                        .setNegativeButton(context.getString(R.string.update_cancel), (dialog, which) -> {
                                            dialog.dismiss();
                                        })
                                        .setPositiveButton(context.getString(R.string.update_agree), (dialog, which) -> {
                                            PermissionUtils.permission(PermissionConfig.INSTANCE.getSdcard().toArray(new String[0]))
                                                    .callback((isAllGranted2, granted2, deniedForever2, denied2) -> {
                                                        if (isAllGranted2) {
                                                            toNotificationManager();
                                                        }
                                                    });
                                            dialog.dismiss();
                                        })
                                        .create().show();
                            }
                        }).request();
            }
        } catch (Exception e) {
            e.printStackTrace();
            toNotificationManager();
        }
    }

    private void toNotificationManager() {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
            try {
                // 检查通知权限是否已经授予
                boolean granted = NotificationManagerCompat.from(context).areNotificationsEnabled();
                if (granted) {
                    start();
                } else {
                    AlertDialog.Builder builder = new AlertDialog.Builder(context);
                    builder.setTitle(context.getString(R.string.update_tips));
                    builder.setMessage(context.getString(R.string.update_open_notiy));
                    builder.setPositiveButton(context.getString(R.string.update_open), (dialog, which) -> {
                        isClickDownload = true;
                        Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
                                .putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
                        context.startActivity(intent);
                    });
                    builder.setNegativeButton(context.getString(R.string.update_cancel), (dialog, which) -> {
                        start();
                    });
                    builder.show();
                }
            } catch (Exception e) {
                e.printStackTrace();
                start();
            }
        } else {
            start();
        }
    }

    private void start() {
        String apkName = downloadUrl.substring(downloadUrl.lastIndexOf("/") + 1);
        try {
            if (apkName.contains("-")) {
                String[] split = apkName.split("-");
                apkName = split[split.length - 1];
                if (apkName.equalsIgnoreCase(".apk")) {
                    apkName = split[0] + ".apk";
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/apk/" + apkName;
        DownloadKtxKt.downloadFile(downloadUrl, path, new DownloadFileListener() {
            @Override
            public void start() {
                isDowning = true;
                NotificationUtils.instance.createNotification(context, logo);
            }

            @Override
            public void connected() {
                XyToastUtils.showShort(context.getString(R.string.update_downing));
            }

            @Override
            public void progress(int progress, long total) {
                Log.i("downApk", "progress: " + progress);
                NotificationUtils.instance.updateNotification(context, progress);
            }

            @Override
            public void success(@NonNull String path) {
                Log.i("downApk", "下载完成");
                isDowning = false;
                NotificationUtils.instance.cancelNotification();
                jumpInstance(path);
            }

            @Override
            public void error(@NonNull String error) {
                isDowning = false;
                XyToastUtils.showShort(context.getString(R.string.update_fail));
                NotificationUtils.instance.cancelNotification();
            }

            @Override
            public void end() {
                isDowning = false;
            }
        });
    }

    //跳转安装apk
    private void jumpInstance(String path) {
        AppUtils.installApp(path);
    }

    public boolean isDowning() {
        return isDowning;
    }

    public void onDestroy() {
        context = null;
    }
}
